package org.wattdepot.cli.command;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Implements the power command for the command line interface.
 * 
 * @author George Lee
 *
 */
public class PowerCommand extends WattDepotCliCommand {
  
  /**
   * Instantiates a new PowerCommand command handler.
   * 
   * @param client The client that will process our commands.
   */
  public PowerCommand(WattDepotClient client) {
    super(client);
  }

  /**
   * Gets the power generated/consumed at a given time.
   * 
   * @param command The command to process.
   * @return The result of the command.
   * 
   * @see org.wattdepot.cli.command.WattDepotCliCommand#doCommand(String)
   */
  @Override
  public String doCommand(String command) {
    PowerCommandType type = PowerCommandType.POWER_GENERATED;
    String source;
    XMLGregorianCalendar time;
    
    StringTokenizer tokenizer = new StringTokenizer(command);
    List<String> tokens = new ArrayList<String>();
    while (tokenizer.hasMoreTokens()) {
      tokens.add(tokenizer.nextToken());
    }
    
    if (tokens.size() != 5) {
      return this.reportError(PARAMETER_COUNT_ERROR);
    }
    
    if (!"timestamp".equals(tokens.get(3))) {
      return this.reportError(PARAMETER_ERROR + tokens.get(3));
    }
    
    if ("consumed".equals(tokens.get(1))) {
      type = PowerCommandType.POWER_CONSUMED;
    }
    else if (!"generated".equals(tokens.get(1))) {
      return this.reportError(PARAMETER_ERROR + tokens.get(1));
    }
    
    source = tokens.get(2);
    
    try {
      time = Tstamp.makeTimestamp(tokens.get(4));
    }
    catch (Exception e) {
      return this.reportError(TSTAMP_ERROR + tokens.get(4));
    }
    
    return this.getPowerForTime(type, source, time);
  }

  /**
   * Gets the power generated/consumed at a given time.
   * 
   * @param type Whether to get the power generated or consumed.
   * @param source The source to get info from.
   * @param time The time to retrieve the information at.
   * @return The amount of power generated/consumed or an error if one occurs.
   */
  private String getPowerForTime(PowerCommandType type, String source, XMLGregorianCalendar time) {
    String result = "";
    Double power;
    
    try {
      if (type == PowerCommandType.POWER_CONSUMED) {
        power = this.client.getPowerConsumed(source, time);
      }
      else {
        power = this.client.getPowerGenerated(source, time);
      }
      
      result = power.toString();
    }
    catch (BadXmlException e) {
      result = this.reportError(BAD_XML_ERROR);
    }
    catch (NotAuthorizedException e) {
      result = this.reportError(CONNECTION_ERROR);
    }
    catch (ResourceNotFoundException e) {
      result = this.reportError(SOURCE_ERROR + source);
    }
    catch (MiscClientException e) {
      result = this.reportError(CONNECTION_ERROR);
    }
    
    return result;
  }

  /**
   * Gets the help string associated with the power command.
   * 
   * @see org.wattdepot.cli.command.WattDepotCliCommand#getHelp()
   * @return Information on how to invoke the power command.
   */
  @Override
  public String getHelp() {
    return "power [generated|consumed] {source} timestamp {timestamp}\n"
      + "  Prints the power generated by the source at the given timestamp.\n";
  }
}
